package mock_or_enum;

import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.Queue;

public // 模拟过程重点是时间 t的两处更新逻辑   以及入队出队位置
class 单线程CPU_1834 {
    public int[] getOrder(int[][] tasks) {
        int cnt = tasks.length;
        // 按照时间线排序  时间一直往下个时间点跳跃  并入队时间小于该时间的 依次取出id
        int[][] tasksI = new int[cnt][3];
        for (int i = 0; i < cnt; i++) tasksI[i] = new int[]{tasks[i][0], tasks[i][1], i}; // 到达时间， 执行时间， 下标
        Arrays.sort(tasksI, (a, b) -> a[0] - b[0]);
        Queue<int[]> queue = new PriorityQueue<>((a, b) -> a[1] == b[1] ? a[2] - b[2] : a[1] - b[1]); // 处理同一时间点之前所有的任务  按条件排序(执行时间和idx)
        // 对每个截止时间点  小于等于该时间点的全部入队排序并保存下标  如没有小于等于该时间点的 跳到下个时间点
        int[] idxRes = new int[cnt];
        for (int t = 1, push = 0, idx = 0; idx < cnt; ) { // 时间 t  入队下标push  返回值下标idx
            while (push < cnt && tasksI[push][0] <= t) {  // 小于该时间的入队
                queue.offer(tasksI[push++]);
            }
            if (queue.isEmpty()) {
                t = tasksI[push][0]; // 已经没有小于该时间的任务了，跳到下一个最小的任务时间
                continue;
            }
            int[] task = queue.poll();
            idxRes[idx++] = task[2]; // 原数组下标
            t += task[1]; //执行需要时间
        }
        return idxRes;
    }
}
